package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.constant.ProductConstant;
import com.atguigu.gulimall.product.dao.*;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.service.CategoryService;
import com.atguigu.gulimall.product.vo.AttrVo;
import com.atguigu.gulimall.product.vo.AttrVoResponse;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Autowired
    private CategoryService categoryService;
    @Autowired
    private AttrGroupDao attrGroupDao;
    @Autowired
    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryBaseList(Map<String, Object> params, Long categoryId, Integer code) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        Optional.ofNullable(params.get("key")).ifPresent(key -> queryWrapper.and(wrapper -> wrapper.eq("attr_id", key).or().like("attr_name", key)));
        if (categoryId != 0) {
            queryWrapper.eq("catelog_id", categoryId);
        }
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                queryWrapper.eq("attr_type", code)
        );
        Map<Long, String> categoryIdNameMap = categoryService.list().stream().collect(Collectors.toMap(CategoryEntity::getCatId, CategoryEntity::getName, (o1, o2) -> o1));
        Map<Long, Long> attrAttrGroupIdMap = attrAttrgroupRelationDao.selectList(new QueryWrapper<>()).stream().collect(Collectors.toMap(AttrAttrgroupRelationEntity::getAttrId, AttrAttrgroupRelationEntity::getAttrGroupId, (o1, o2) -> o1));
        List<AttrVo> handleList = page.getRecords().stream().map(item -> {
            AttrVo attrVo = new AttrVo();
            BeanUtils.copyProperties(item, attrVo);
            Optional.ofNullable(categoryIdNameMap.get(item.getCatelogId())).ifPresent(attrVo::setCatelogName);
            Optional.ofNullable(attrAttrGroupIdMap.get(item.getAttrId())).ifPresent(attrGroupId -> attrVo.setGroupName(attrGroupDao.selectById(attrGroupId).getAttrGroupName()));
            return attrVo;
        }).collect(Collectors.toList());
        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(handleList);
        return pageUtils;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDetail(AttrVo attrVo) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo,attrEntity);
        this.save(attrEntity);
        if (ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode().equals(attrVo.getAttrType())) {
            attrAttrgroupRelationDao.insert(new AttrAttrgroupRelationEntity(attrEntity.getAttrId(), attrVo.getAttrGroupId()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDetail(AttrVo attrVo) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo,attrEntity);
        this.updateById(attrEntity);
        if (ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode().equals(attrVo.getAttrType())) {
            Integer count = attrAttrgroupRelationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
            if (count == 0) {
                attrAttrgroupRelationDao.insert(new AttrAttrgroupRelationEntity(attrEntity.getAttrId(), attrVo.getAttrGroupId()));
            } else {
                attrAttrgroupRelationDao.update(AttrAttrgroupRelationEntity.builder().attrGroupId(attrVo.getAttrGroupId()).build(), new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrVo.getAttrId()));
            }
        }
    }

    @Override
    public AttrVoResponse getDetail(Long attrId) {
        AttrVoResponse attrVoResponse = new AttrVoResponse();
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity, attrVoResponse);
        attrVoResponse.setCatelogPath(this.categoryService.getCatelogIds(attrEntity.getCatelogId()));
        if (ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode().equals(attrVoResponse.getAttrType())) {
            Optional.ofNullable(attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()))).ifPresent(present -> attrVoResponse.setAttrGroupId(present.getAttrGroupId()));
        }
        return attrVoResponse;
    }

    /**
     * 根据分组ID找到关联的所有属性
     * @param attrgroudId 分组ID
     * @return java.util.List<com.atguigu.gulimall.product.entity.AttrEntity>
     */
    @Override
    public List<AttrEntity> attrRelation(Long attrgroudId) {
        List<AttrAttrgroupRelationEntity> attrRelationEntities = this.attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroudId));
        List<Long> attrIds = attrRelationEntities.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(attrIds)) {
            return null;
        }
        return this.baseMapper.selectBatchIds(attrIds);
    }

    @Override
    public PageUtils noAttrRelation(Map<String, Object> params, Long attrgroupId) {
        Long catelogId = this.attrGroupDao.selectById(attrgroupId).getCatelogId();
        List<Long> groupIdList = this.attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId)).stream().map(AttrGroupEntity::getAttrGroupId).collect(Collectors.toList());
        List<AttrAttrgroupRelationEntity> attrRelationEntities = this.attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", groupIdList));
        List<Long> subtractList = new ArrayList<>(CollectionUtils.subtract(this.baseMapper.selectList(new QueryWrapper<AttrEntity>().eq("catelog_id", catelogId).eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode())).stream().map(AttrEntity::getAttrId).collect(Collectors.toList()), attrRelationEntities.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList())));
        if (CollectionUtils.isEmpty(subtractList)) {
            return new PageUtils();
        }
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().in("attr_id", subtractList);
        String key = (String) params.get("key");
        if (StringUtils.isNotBlank(key)) {
            wrapper.and(queryWrapper -> queryWrapper.eq("attr_id", key).or().like("attr_name", key));
        }
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);
        return new PageUtils(page);
    }

}
